package com.piggy.logi.sys.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.piggy.common.core.constant.UserConstants;
import com.piggy.common.core.utils.sql.SqlUtil;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.logi.sys.api.domain.LogiSysDept;
import com.piggy.logi.sys.domain.*;
import com.piggy.logi.sys.enums.*;
import com.piggy.logi.sys.service.*;
import com.piggy.logi.sys.vo.LogiIndexStatisticsVo;
import com.piggy.logi.sys.vo.LogiPlatIndexStatisticsVo;
import com.piggy.logi.sys.vo.LogiPlatTodoMattersVo;
import com.piggy.logi.sys.vo.LogiTodoMattersVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Objects;

/**
 * 首页统计Service业务层处理
 *
 * @author fengxy
 * @date 2023/10/17 21:54
 **/
@Slf4j
@Service
public class LogiIndexStatisticsServiceImpl implements ILogiIndexStatisticsService {

    @Resource
    private ILogiWaybillService logiWaybillService;

    @Resource
    private ILogiCustomerService logiCustomerService;

    @Resource
    private ILogiProjectService logiProjectService;

    @Resource
    private ILogiCarrierService logiCarrierService;

    @Resource
    private ILogiCarrierDriverService logiCarrierDriverService;

    @Resource
    private ILogiCarrierCarService logiCarrierCarService;

    @Resource
    private ILogiSysDeptService logiSysDeptService;

    @Resource
    private ILogiWaybillGoodSourceService logiWaybillGoodSourceService;

    @Resource
    private ILogiScheduleService logiScheduleService;

    @Resource
    private ILogiKefuFineService logiKefuFineService;

    @Resource
    private ILogiKefuIssueService logiKefuIssueService;

    @Resource
    private ILogiWaybillPayableService logiWaybillPayableService;

    @Resource
    private ILogiWaybillReceivableService logiWaybillReceivableService;

    @Override
    public LogiIndexStatisticsVo indexStatistics(Long deptId) {
        // 返回对象
        LogiIndexStatisticsVo indexStatisticsVo = new LogiIndexStatisticsVo();
        // 总客户数（家）
        indexStatisticsVo.setCustomerTotalNum(logiCustomerService.count(SqlUtil.dataPermissionFilter(LogiCustomer.class, deptId)));
        // 总项目数（个）
        indexStatisticsVo.setProjectTotalNum(logiProjectService.count(SqlUtil.dataPermissionFilter(LogiProject.class, deptId)));
        // 总合作承运方（家）
        indexStatisticsVo.setCarrierTotalNum(logiCarrierService.count(SqlUtil.dataPermissionFilter(LogiCarrier.class, deptId)));
        // 总合作司机（家）
        indexStatisticsVo.setDriverTotalNum(logiCarrierDriverService.count(SqlUtil.dataPermissionFilter(LogiCarrierDriver.class, deptId)));
        // 总车辆（辆）
        indexStatisticsVo.setCarTotalNum(logiCarrierCarService.count(SqlUtil.dataPermissionFilter(LogiCarrierCar.class, deptId)));
        // 总网点（个）
        indexStatisticsVo.setBranchTotalNum(logiSysDeptService.count(SqlUtil.dataPermissionFilter(LogiSysDept.class, deptId).eq(LogiSysDept::getDeptType, DeptTypeEnum.BRANCH.getType())));
        // 总运输量（吨）
        indexStatisticsVo.setTransportTotalNum(logiWaybillGoodSourceService.list(SqlUtil.dataPermissionFilter(LogiWaybillGoodSource.class, deptId).exists("select 1 from logi_waybill where logi_waybill.waybill_id = logi_waybill_good_source.waybill_id and logi_waybill.status != " + WaybillStatusEnum.CANCEL.getCode())).stream().mapToDouble(a -> StrUtil.isNotBlank(a.getWeight()) ? Double.parseDouble(a.getWeight()) : 0).sum());
        // 完成运输量（吨）
        indexStatisticsVo.setFinishTransportNum(logiWaybillGoodSourceService.list(SqlUtil.dataPermissionFilter(LogiWaybillGoodSource.class, deptId).exists("select 1 from logi_waybill where logi_waybill.waybill_id = logi_waybill_good_source.waybill_id and logi_waybill.status = " + WaybillStatusEnum.COMPLETED.getCode())).stream().mapToDouble(a -> StrUtil.isNotBlank(a.getWeight()) ? Double.parseDouble(a.getWeight()) : 0).sum());
        // 挂失运单（个）
        indexStatisticsVo.setLossWayBillNum(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).exists("select 1 from logi_waybill_kefu_log where logi_waybill_kefu_log.waybill_id = logi_waybill.waybill_id and logi_waybill_kefu_log.log_type = '" + WaybillKefuLogTypeEnum.LOG_CAGO_CONTROL.getCode() + "' and logi_waybill_kefu_log.cargo_control_status = 1")));
        // 解挂运单（个）
        indexStatisticsVo.setUnhangWayBillNum(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).exists("select 1 from logi_waybill_kefu_log where logi_waybill_kefu_log.waybill_id = logi_waybill.waybill_id and logi_waybill_kefu_log.log_type = '" + WaybillKefuLogTypeEnum.LOG_CAGO_CONTROL.getCode() + "' and logi_waybill_kefu_log.cargo_control_status = 2")));
        // 总运单量（个）
        indexStatisticsVo.setWayBillTotalNum(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId)));
        // 完成运单量（个）
        indexStatisticsVo.setFinishWayBillNum(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.COMPLETED.getCode())));
        // 待办问题（个）
        indexStatisticsVo.setTodoProblemNum(logiKefuIssueService.count(SqlUtil.dataPermissionFilter(LogiKefuIssue.class, deptId).eq(LogiKefuIssue::getIssueStatus, 0)));
        // 已办问题（个）
        indexStatisticsVo.setDoneProblemNum(logiKefuIssueService.count(SqlUtil.dataPermissionFilter(LogiKefuIssue.class, deptId).eq(LogiKefuIssue::getIssueStatus, 1)));
        // 总发车车次（次）
        indexStatisticsVo.setDispatchCarTotalNum(logiScheduleService.count(SqlUtil.dataPermissionFilter(LogiSchedule.class, deptId)));
        // 本月发车车次（次）
        indexStatisticsVo.setDispatchCarCurMonthNum(logiScheduleService.count(SqlUtil.dataPermissionFilter(LogiSchedule.class, deptId).between(LogiSchedule::getDepartTime, DateUtil.beginOfMonth(DateUtil.date()), DateUtil.endOfMonth(DateUtil.date()))));
        // 登记罚款（元）
        indexStatisticsVo.setRecordPenalty(logiKefuFineService.list(SqlUtil.dataPermissionFilter(LogiKefuFine.class, deptId)).stream().map(LogiKefuFine::getFineAmt).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 控货运单（个）
        indexStatisticsVo.setControlWayBillNum(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).exists("select 1 from logi_waybill_kefu_log where logi_waybill_kefu_log.waybill_id = logi_waybill.waybill_id and  logi_waybill_kefu_log.log_type = '" + WaybillKefuLogTypeEnum.LOG_ENABLE.getCode() + "' and logi_waybill_kefu_log.cargo_control_status = 1")));
        // 放货运单（个）
        indexStatisticsVo.setReleaseWayBillNum(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).exists("select 1 from logi_waybill_kefu_log where logi_waybill_kefu_log.waybill_id = logi_waybill.waybill_id and  logi_waybill_kefu_log.log_type = '" + WaybillKefuLogTypeEnum.LOG_ENABLE.getCode() + "' and logi_waybill_kefu_log.cargo_control_status = 2")));
        // 总应付账款（元）
        indexStatisticsVo.setPayableTotal(logiWaybillPayableService.list(SqlUtil.dataPermissionFilter(LogiWaybillPayable.class, deptId)).stream().map(LogiWaybillPayable::getPayableAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 总应收账款（元）
        indexStatisticsVo.setReceivableTotal(logiWaybillReceivableService.list(SqlUtil.dataPermissionFilter(LogiWaybillReceivable.class, deptId)).stream().map(LogiWaybillReceivable::getReceivableAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 返回统计结果
        return indexStatisticsVo;
    }

    @Override
    public LogiTodoMattersVo todoMatters(Long deptId) {
        // 返回对象
        LogiTodoMattersVo todoMattersVo = new LogiTodoMattersVo();
        // 待提交运单
        todoMattersVo.setWaitSubmitWaybill(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.WAIT_SUBMIT.getCode())));
        // 待调度运单
        todoMattersVo.setSubmitedWaybill(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.SUBMITED.getCode())));
        // 待提货运单
        todoMattersVo.setScheduledWaybill(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.SCHEDULED.getCode())));
        // 提货中运单
        todoMattersVo.setPickupingWaybill(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.PICKUPING.getCode())));
        // 待提货车次
        todoMattersVo.setScheduledCar(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.SCHEDULED.getCode())));
        // 提货中车次
        todoMattersVo.setPickupingCar(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.PICKUPING.getCode())));
        // 待签收运单
        todoMattersVo.setArrivalWaybill(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.ARRIVAL.getCode())));
        // 已签收运单
        todoMattersVo.setSignatureWaybill(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.SIGNATURE.getCode())));
        // 在途中车次
        todoMattersVo.setDepartureCar(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.DEPARTED.getCode())));
        // 已到达车次
        todoMattersVo.setArrivalCar(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.ARRIVED.getCode())));
        // 已完成运单
        todoMattersVo.setCompletedWaybill(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getStatus, WaybillStatusEnum.COMPLETED.getCode())));
        // 已完成车次
        todoMattersVo.setCompletedCar(logiWaybillService.count(SqlUtil.dataPermissionFilter(LogiWaybill.class, deptId).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.FINSHED.getCode())));
        // 创建司机账号
        todoMattersVo.setCreateDriver(logiCarrierDriverService.count(SqlUtil.dataPermissionFilter(LogiCarrierDriver.class, deptId).eq(LogiCarrierDriver::getDeptId, deptId)));
        // 返回统计结果
        return todoMattersVo;
    }

    @Override
    public LogiPlatIndexStatisticsVo platIndexStatistics() {
        // 返回对象
        LogiPlatIndexStatisticsVo platIndexStatisticsVo = new LogiPlatIndexStatisticsVo();
        // 权限控制：部门为：物流运营总平台 的才进行统计
        if (Objects.requireNonNull(SecurityUtils.getDeptId()).intValue() == OrgDeptIdEnum.SYSADMIN.getCode()) {
            // 注册物流公司（家）
            platIndexStatisticsVo.setDeptTotalNum(logiSysDeptService.count(Wrappers.lambdaQuery(LogiSysDept.class)));
            // 开通物流公司（户）
            platIndexStatisticsVo.setEnableDeptNum(logiSysDeptService.count(Wrappers.lambdaQuery(LogiSysDept.class).eq(LogiSysDept::getParentId, 0).eq(LogiSysDept::getStatus, UserConstants.DEPT_NORMAL)));
            // 未通物流公司（户）
            platIndexStatisticsVo.setDisableDeptNum(logiSysDeptService.count(Wrappers.lambdaQuery(LogiSysDept.class).eq(LogiSysDept::getParentId, 0).eq(LogiSysDept::getStatus, UserConstants.DEPT_DISABLE)));
            // 注册个体司机（个）
            platIndexStatisticsVo.setDriverTotalNum(logiCarrierDriverService.count(Wrappers.lambdaQuery(LogiCarrierDriver.class)));
            // 开通个体司机（户）
            platIndexStatisticsVo.setEnableDriverNum(logiCarrierDriverService.count(Wrappers.lambdaQuery(LogiCarrierDriver.class).eq(LogiCarrierDriver::getEnableStatus, 0)));
            // 未通个体司机（户）
            platIndexStatisticsVo.setDisableDriverNum(logiCarrierDriverService.count(Wrappers.lambdaQuery(LogiCarrierDriver.class).eq(LogiCarrierDriver::getEnableStatus, 1)));
            // 总运单量（个）
            platIndexStatisticsVo.setWayBillTotalNum(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class)));
            // 完成运单量（个）
            platIndexStatisticsVo.setFinishWayBillNum(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.COMPLETED.getCode())));
            // 总发车车次（次）
            platIndexStatisticsVo.setDispatchCarTotalNum(logiScheduleService.count(Wrappers.lambdaQuery(LogiSchedule.class)));
            // 本月发车车次（次）
            platIndexStatisticsVo.setDispatchCarCurMonthNum(logiScheduleService.count(Wrappers.lambdaQuery(LogiSchedule.class).between(LogiSchedule::getDepartTime, DateUtil.beginOfMonth(DateUtil.date()), DateUtil.endOfMonth(DateUtil.date()))));
            // 总应付账款（元）
            platIndexStatisticsVo.setPayableTotal(logiWaybillPayableService.list(Wrappers.lambdaQuery(LogiWaybillPayable.class)).stream().map(LogiWaybillPayable::getPayableAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
            // 总应收账款（元）
            platIndexStatisticsVo.setReceivableTotal(logiWaybillReceivableService.list(Wrappers.lambdaQuery(LogiWaybillReceivable.class)).stream().map(LogiWaybillReceivable::getReceivableAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        }
        // 返回统计结果
        return platIndexStatisticsVo;
    }

    @Override
    public LogiPlatTodoMattersVo platTodoMatters() {
        // 返回对象
        LogiPlatTodoMattersVo platTodoMattersVo = new LogiPlatTodoMattersVo();
        // 权限控制：部门为：物流运营总平台 的才进行统计
        if (Objects.requireNonNull(SecurityUtils.getDeptId()).intValue() == OrgDeptIdEnum.SYSADMIN.getCode()) {
            // 待提交运单
            platTodoMattersVo.setWaitSubmitWaybill(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.WAIT_SUBMIT.getCode())));
            // 待调度运单
            platTodoMattersVo.setSubmitedWaybill(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.SUBMITED.getCode())));
            // 待提货运单
            platTodoMattersVo.setScheduledWaybill(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.SCHEDULED.getCode())));
            // 提货中运单
            platTodoMattersVo.setPickupingWaybill(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.PICKUPING.getCode())));
            // 待提货车次
            platTodoMattersVo.setScheduledCar(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.SCHEDULED.getCode())));
            // 提货中车次
            platTodoMattersVo.setPickupingCar(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.PICKUPING.getCode())));
            // 待签收运单
            platTodoMattersVo.setArrivalWaybill(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.ARRIVAL.getCode())));
            // 已签收运单
            platTodoMattersVo.setSignatureWaybill(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.SIGNATURE.getCode())));
            // 在途中车次
            platTodoMattersVo.setDepartureCar(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.DEPARTED.getCode())));
            // 已到达车次
            platTodoMattersVo.setArrivalCar(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.ARRIVED.getCode())));
            // 已完成运单
            platTodoMattersVo.setCompletedWaybill(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getStatus, WaybillStatusEnum.COMPLETED.getCode())));
            // 已完成车次
            platTodoMattersVo.setCompletedCar(logiWaybillService.count(Wrappers.lambdaQuery(LogiWaybill.class).eq(LogiWaybill::getScheduleStatus, ScheduleStatusEnum.FINSHED.getCode())));
            // 未结应付运单
            platTodoMattersVo.setNoSettlePayableNum(logiWaybillPayableService.count(Wrappers.lambdaQuery(LogiWaybillPayable.class).eq(LogiWaybillPayable::getStatus, SettleStatusEnum.NOT_SETTLE.getCode())));
            // 未结应收运单
            platTodoMattersVo.setNoSettleReceivableNum(logiWaybillReceivableService.count(Wrappers.lambdaQuery(LogiWaybillReceivable.class).eq(LogiWaybillReceivable::getStatus, SettleStatusEnum.NOT_SETTLE.getCode())));
        }
        // 返回统计结果
        return platTodoMattersVo;
    }
}
